{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Two guys meet\n",
    "\n",
    "This example is intended to illustrate the use of `DiscreteEvents.jl`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "using DiscreteEvents, Printf"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Since we implement the encounter as state machines, we need some definitions. For simplicity we don't implement a separate state here but only events."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "struct Guy\n",
    "    name\n",
    "end\n",
    "\n",
    "abstract type Encounter end\n",
    "struct Meet <: Encounter\n",
    "    someone\n",
    "end\n",
    "struct Greet <: Encounter\n",
    "    num\n",
    "    from\n",
    "end\n",
    "struct Response <: Encounter\n",
    "    num\n",
    "    from\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We have some convenience functions. `tau()` gives the current simulation time."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "say (generic function with 1 method)"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "comm = (\"Nice to meet you!\", \"How are you?\", \"Have a nice day!\", \"bye bye\")\n",
    "say(name, n) =  @printf(\"%5.2f s, %s: %s\\n\", tau(), name, comm[n])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we implement the actions between the state machines as different methods of a `step!`-function, which will be called according to events. Here we use three `DiscreteEvents.jl`-features:\n",
    "\n",
    "- italic `𝐶` (\\itC+Tab) or `Clk` is the central clock,\n",
    "- `SimFunction`, alias `SF` prepares a function for later execution,\n",
    "- `event!` schedules a `SimFunction` for an execution after some time. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "step! (generic function with 3 methods)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "function step!(me::Guy, σ::Meet)\n",
    "    event!(𝐶, SF(step!, σ.someone, Greet(1, me)), after, 2*rand())\n",
    "    say(me.name, 1)\n",
    "end\n",
    "\n",
    "function step!(me::Guy, σ::Greet)\n",
    "    if σ.num < 3\n",
    "        event!(𝐶, SF(step!, σ.from, Response(σ.num, me)), after, 2*rand())\n",
    "        say(me.name, σ.num)\n",
    "    else\n",
    "        say(me.name, 4)\n",
    "    end\n",
    "end\n",
    "\n",
    "function step!(me::Guy, σ::Response)\n",
    "    event!(𝐶, SF(step!, σ.from, Greet(σ.num+1, me)), after, 2*rand())\n",
    "    say(me.name, σ.num+1)\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we need two guys (state machines), define a starting event and `run` it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " 9.00 s, Foo: Nice to meet you!\n",
      " 9.57 s, Bar: Nice to meet you!\n",
      " 9.80 s, Foo: How are you?\n",
      "10.65 s, Bar: How are you?\n",
      "11.42 s, Foo: Have a nice day!\n",
      "12.51 s, Bar: bye bye\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "\"run! finished with 6 clock events, 0 sample steps, simulation time: 20.0\""
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "foo = Guy(\"Foo\")\n",
    "bar = Guy(\"Bar\")\n",
    "\n",
    "event!(𝐶, SF(step!, foo, Meet(bar)), at, 10*rand())\n",
    "run!(𝐶, 20)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally we should reset the clock for further simulations:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"clock reset to t₀=0.0, sampling rate Δt=0.0.\""
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "reset!(𝐶)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "@webio": {
   "lastCommId": null,
   "lastKernelId": null
  },
  "kernelspec": {
   "display_name": "Julia 1.2.0",
   "language": "julia",
   "name": "julia-1.2"
  },
  "language_info": {
   "file_extension": ".jl",
   "mimetype": "application/julia",
   "name": "julia",
   "version": "1.2.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
